package io.xxx.omni.osc.schedule

import io.xxx.omni.osc.client.PlatformClient
import io.xxx.omni.osc.sync.Porter
import org.apache.shardingsphere.elasticjob.api.JobConfiguration
import org.apache.shardingsphere.elasticjob.lite.api.bootstrap.impl.ScheduleJobBootstrap
import org.apache.shardingsphere.elasticjob.reg.base.CoordinatorRegistryCenter
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.ApplicationArguments
import org.springframework.boot.ApplicationRunner
import org.springframework.context.ApplicationContext
import org.springframework.context.annotation.Configuration
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PutMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
@RequestMapping("/porters")
@Configuration
class PorterFactory : ApplicationRunner {

    private val log = LoggerFactory.getLogger(javaClass)

    @Autowired
    private lateinit var applicationContext: ApplicationContext

    @Autowired
    private lateinit var registryCenter: CoordinatorRegistryCenter

    @Autowired
    private lateinit var platformClient: PlatformClient

    private val bootstraps = mutableMapOf<String, ScheduleJobBootstrap>()
    private val porters = mutableMapOf<String, Porter<*, *>>()

    override fun run(args: ApplicationArguments) {
        val platforms = platformClient.getAll()
            .associateBy { it.id }
        val porters = applicationContext.getBeansOfType(Porter::class.java)
        porters
            .filter {
                val porter = it.value
                val platform = platforms[porter.platformId()]
                platform != null && platform.enabled
            }
            .forEach { (porterName, porter) ->
                val platformId = porter.platformId()
                val jobConfig = JobConfiguration
                    .newBuilder(porterName, 1)
                    .cron(porter.cron)
                    .description("${platformId}数据同步任务")
                    .build()
                val bootstrap = ScheduleJobBootstrap(registryCenter, porter, jobConfig)
                bootstrap.schedule()

                bootstraps[platformId] = bootstrap
                this.porters[platformId] = porter
                log.info("启动任务: ${jobConfig.description}")
            }
    }

    @PutMapping("/{platformId}/shutdown")
    fun shutdown(@PathVariable platformId: String): Boolean {
        val bootstrap = bootstraps[platformId]
        bootstrap?.shutdown()
        return true
    }
}